/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

package com.facebook.imagepipeline.producers;

import com.facebook.common.memory.PooledByteBufferFactory;
import com.facebook.common.util.UriUtil;
import com.facebook.imagepipeline.common.ResizeOptions;
import com.facebook.imagepipeline.image.EncodedImage;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imageutils.JfifUtil;
import com.facebook.imagepipeline.annotation.Nullable;
import com.oszc.bbhmlibrary.utils.LogUtil;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.agp.utils.Rect;
import ohos.data.dataability.DataAbilityPredicates;
import ohos.data.resultset.ResultSet;
import ohos.utils.net.Uri;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.concurrent.Executor;

/**
 * Represents a local content Uri fetch producer.
 */
public class LocalContentUriThumbnailFetchProducer extends LocalFetchProducer
        implements ThumbnailProducer<EncodedImage> {

    private static final Class<?> TAG = LocalContentUriThumbnailFetchProducer.class;

    public static final String PRODUCER_NAME = "LocalContentUriThumbnailFetchProducer";

    private static final String[] PROJECTION =
            new String[]{"_id", "_data"};
    private static final String[] THUMBNAIL_PROJECTION =
            new String[]{"_data"};

    private static final Rect MINI_THUMBNAIL_DIMENSIONS = new Rect(0, 0, 512, 384);
    private static final Rect MICRO_THUMBNAIL_DIMENSIONS = new Rect(0, 0, 96, 96);

    private static final int NO_THUMBNAIL = 0;

    private final DataAbilityHelper mContentResolver;

    public LocalContentUriThumbnailFetchProducer(
            Executor executor,
            PooledByteBufferFactory pooledByteBufferFactory,
            DataAbilityHelper contentResolver) {
        super(executor, pooledByteBufferFactory);
        mContentResolver = contentResolver;
    }

    @Override
    public boolean canProvideImageForSize(ResizeOptions resizeOptions) {
        boolean result = ThumbnailSizeChecker.isImageBigEnough(
                MINI_THUMBNAIL_DIMENSIONS.getWidth(), MINI_THUMBNAIL_DIMENSIONS.getHeight(), resizeOptions);

        LogUtil.error(TAG.getSimpleName(),"canProvideImageForSize:"+result);
        return result;
    }

    @Override
    protected @Nullable
    EncodedImage getEncodedImage(ImageRequest imageRequest) throws IOException, DataAbilityRemoteException {
        LogUtil.error(TAG.getSimpleName(),"getEncodedImage A");
        Uri uri = imageRequest.getSourceUri();
        LogUtil.error(TAG.getSimpleName(),"getEncodedImage --> "+uri.toString());
        if (UriUtil.isLocalCameraUri(uri)) {
            return getCameraImage(uri, imageRequest.getResizeOptions());
        }

        return null;
    }

    private @Nullable
    EncodedImage getCameraImage(Uri uri, @Nullable ResizeOptions resizeOptions)
            throws IOException, DataAbilityRemoteException {
        LogUtil.error(TAG.getSimpleName(),"getCameraImage");
        if (resizeOptions == null) {
            return null;
        }
        @Nullable ResultSet cursor = mContentResolver.query(uri, PROJECTION, null);
        if (cursor == null) {
            return null;
        }
        try {
            if (cursor.goToFirstRow()) {
                final int imageIdColumnIndex = cursor.getColumnIndexForName("_id");
                final EncodedImage thumbnail =
                        getThumbnail(resizeOptions, cursor.getLong(imageIdColumnIndex));
                if (thumbnail != null) {
                    final String pathname =
                            cursor.getString(cursor.getColumnIndexForName("_data"));
                    thumbnail.setRotationAngle(getRotationAngle(pathname));
                    return thumbnail;
                }
            }
        } finally {
            cursor.close();
        }
        return null;
    }

    // Gets the smallest possible thumbnail that is bigger than the requested size in the resize
    // options or null if either the thumbnails are smaller than the requested size or there are no
    // stored thumbnails.
    private @Nullable
    EncodedImage getThumbnail(ResizeOptions resizeOptions, long imageId)
            throws IOException, DataAbilityRemoteException {
        int thumbnailKind = getThumbnailKind(resizeOptions);
        if (thumbnailKind == NO_THUMBNAIL) {
            return null;
        }
        LogUtil.error(TAG.getSimpleName(),"getThumbnail");

        Uri parse = Uri.parse("content://media/external/images/thumbnails");
        DataAbilityPredicates dataAbilityPredicates = new DataAbilityPredicates("image_id" + " = " + imageId + " AND " + "kind = " + thumbnailKind);
        @Nullable
        ResultSet thumbnailCursor = mContentResolver.query(parse, THUMBNAIL_PROJECTION, dataAbilityPredicates);


        if (thumbnailCursor == null) {
            return null;
        }
        try {
            if (thumbnailCursor.goToFirstRow()) {
                final String thumbnailUri =
                        thumbnailCursor.getString(
                                thumbnailCursor.getColumnIndexForName("_data"));
                if (new File(thumbnailUri).exists()) {
                    return getEncodedImage(new FileInputStream(thumbnailUri), getLength(thumbnailUri));
                }
            }
        } finally {
            thumbnailCursor.close();
        }
        return null;
    }

    // Returns the smallest possible thumbnail kind that has an acceptable size (meaning the resize
    // options requested size is smaller than 4/3 its size).
    // We can add a small interval of acceptance over the size of the thumbnail since the quality lost
    // when scaling it to fit a view will not be significant.
    private static int getThumbnailKind(ResizeOptions resizeOptions) {
        if (ThumbnailSizeChecker.isImageBigEnough(
                MICRO_THUMBNAIL_DIMENSIONS.getWidth(), MICRO_THUMBNAIL_DIMENSIONS.getHeight(), resizeOptions)) {
            return 3;
        } else if (ThumbnailSizeChecker.isImageBigEnough(
                MINI_THUMBNAIL_DIMENSIONS.getWidth(), MINI_THUMBNAIL_DIMENSIONS.getHeight(), resizeOptions)) {
            return 1;
        } else {
            return NO_THUMBNAIL;
        }
    }

    private static int getLength(String pathname) {
        return pathname == null ? -1 : (int) new File(pathname).length();
    }

    @Override
    protected String getProducerName() {
        return PRODUCER_NAME;
    }

    private static int getRotationAngle(String pathname) {
        if (pathname != null) {
            //ExifInterface exif = new ExifInterface(pathname);
            return JfifUtil.getAutoRotateAngleFromOrientation(1);
        }
        return 0;
    }
}
